package cn.rkylin.oms.order.adapter;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.rkylin.core.IDataBaseFactory;
import cn.rkylin.oms.common.dto.DBLog;
import cn.rkylin.oms.common.utils.DateUtil;
import cn.rkylin.oms.common.utils.LogUtil;
import cn.rkylin.oms.order.domain.Order;
import cn.rkylin.oms.order.domain.taobao.TopOrder;
import cn.rkylin.oms.order.domain.taobao.TopTrade;
import cn.rkylin.oms.order.domain.taobao.TopTradeOrder;
import cn.rkylin.oms.order.service.OrderServiceImpl;
import cn.rkylin.oms.order.vo.Logistic_service_tag;
import cn.rkylin.oms.order.vo.Logistics_tag;
import cn.rkylin.oms.order.vo.Promotion_detail;
import cn.rkylin.oms.order.vo.TaoBaoOrder;
import cn.rkylin.oms.order.vo.TaoBaoResponse;
import cn.rkylin.oms.order.vo.Trade;
import cn.rkylin.oms.order.vo.TradeFullInfo;
import cn.rkylin.oms.sysOrder.service.SysOrderServiceImpl;
import cn.rkylin.oms.sysOrder.vo.SysOrderVO;
import cn.rkylin.oms.system.shop.domain.Shop;
import cn.rkylin.oms.system.shop.vo.ShopVO;
import cn.rkylin.oms.warehouse.shiporder.request.RequestTradeOfflineSend;
import cn.rkylin.oms.warehouse.shiporder.service.ShiporderServiceImpl;
import cn.rkylin.oms.warehouse.shiporder.vo.ShiporderVO;

/**
 * 淘宝订单代理
 * 
 * @author js
 * @version 1.0
 * @created 13-1月-2017 09:11:16
 */
@Service("taoBaoOrderVisitor")
public class TaoBaoOrderVisitor extends OrderVisitor {
	private static final Log logger = LogFactory.getLog(TaoBaoOrderVisitor.class);
	/*
	 * 以店铺为单位的连接池map
	 */
	private static Map<String, BasicDataSource> dataSourceMap = new HashMap<String, BasicDataSource>();

	@Autowired
	private LogUtil logUtil;

	private static final String TABLENAME = "jdp_tb_trade";

	@Value("${oms.address}")
	private String omsAddres;

	@Autowired
	private ShiporderServiceImpl shiporderServiceImpl;

	@Autowired
	private SysOrderServiceImpl sysOrderServiceImpl;

	@Autowired
	OrderServiceImpl orderServiceImpl;

	/**
	 * 数据库访问对象
	 */
	@Autowired
	private IDataBaseFactory dao;

	public void finalize() throws Throwable {
		super.finalize();
	}

	/**
	 * 构造函数
	 */
	public TaoBaoOrderVisitor() {
		//
	}

	/**
	 * 通过tid下载订单
	 *
	 * @param tid
	 * @param shopVO
	 * @return
	 */
	public Map<String, Object> getOrderObject(String tid, Shop shopVO) {
		Connection conn = null; // 数据库连接
		Map<String, Object> map = null; // 返回值，里面分别保存trade和order的数据
		StringBuilder sql = new StringBuilder(); // sql语句
		List<TaoBaoOrder> list = new ArrayList<TaoBaoOrder>(); // 解析检索得到的json
		QueryRunner qr = new QueryRunner();

		if (shopVO == null) {
			return null;
		}
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection(shopVO.getDbUrl(), shopVO.getDbUsername(), shopVO.getDbPassword());
			// 生成SQL语句
			sql.append(" select tid,jdp_response");
			sql.append("   from " + TABLENAME);
			sql.append("  where  seller_nick = '" + shopVO.getShopAccount() + "'");
			sql.append("    and tid = '" + tid + "'");
			List<Map<String, Object>> mapLs = qr.query(conn, sql.toString(), new MapListHandler());
			for (Map<String, Object> resultmap : mapLs) {
				TaoBaoOrder taoBaoOrder = new TaoBaoOrder();
				taoBaoOrder.setTid(resultmap.get("tid").toString());
				taoBaoOrder.setTaoBaoResponse(
						getObjectFromJson(resultmap.get("jdp_response").toString(), "trade_fullinfo_get_response"));
				list.add(taoBaoOrder);
			}

			// 关闭数据库连接
			DbUtils.closeQuietly(conn);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(tid, "通过订单号下载订单", shopVO.getShopAccount(), e.getMessage()));
		} catch (SQLException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(tid, "通过订单号下载订单", shopVO.getShopAccount(), e.getMessage()));
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(tid, "通过订单号下载订单", shopVO.getShopAccount(), e.getMessage()));
		} finally {
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
				logger.error(e.getMessage(), e);
			}
		}
		return map;
	}

	/**
	 * 利用jdbc直接访问聚石塔的表取得返回的结果集
	 *
	 * @param paramMap
	 * @return 里面分别保存trade和order的数据
	 */
	private Map<String, Object> getTradeFromTaoBao(Map<String, Object> paramMap) {

		Connection conn = null; // 数据库连接
		Map<String, Object> map = null; // 返回值，里面分别保存trade和order的数据
		StringBuilder sql = new StringBuilder(); // sql语句
		List<TaoBaoOrder> list = new ArrayList<TaoBaoOrder>(); // 解析检索得到的json
		QueryRunner qr = new QueryRunner();
		// 如果店铺名称没有，就取消操作
		ShopVO shopVO = (ShopVO) paramMap.get("shop");
		if (shopVO == null) {
			return null;
		}
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection(shopVO.getDbUrl(), shopVO.getDbUsername(), shopVO.getDbPassword());
			// conn = DriverManager.getConnection(URL, USER, PASSWORD);
			// 生成SQL语句
			sql.append(" select tid,jdp_response");
			sql.append("   from " + TABLENAME);
			sql.append("  where  seller_nick = '" + shopVO.getShopAccount() + "'");
			if (paramMap.containsKey("startTime") && paramMap.containsKey("endTime")
					&& paramMap.get("startTime") != null && paramMap.get("endTime") != null) {
				sql.append(" and jdp_modified >= '" + paramMap.get("startTime") + "'");
				sql.append(" and jdp_modified <= '" + paramMap.get("endTime") + "'");
			}
			// 手动下载用
			if (StringUtils.isNotBlank((String) paramMap.get("tid"))) {
				sql.append(" and tid = '" + paramMap.get("tid") + "'");
			}
			// 手动下载用
			if (StringUtils.isNotBlank((String) paramMap.get("buyerNick"))) {
				sql.append(" and buyer_nick = '" + paramMap.get("buyerNick") + "'");
			}

			List<Map<String, Object>> mapLs = qr.query(conn, sql.toString(), new MapListHandler());
			for (Map<String, Object> resultmap : mapLs) {
				TaoBaoOrder taoBaoOrder = new TaoBaoOrder();
				taoBaoOrder.setTid(resultmap.get("tid").toString());
				taoBaoOrder.setTaoBaoResponse(
						getObjectFromJson(resultmap.get("jdp_response").toString(), "trade_fullinfo_get_response"));
				list.add(taoBaoOrder);
			}

			// 关闭数据库连接
			DbUtils.closeQuietly(conn);

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(shopVO.getShopAccount(), "通过店铺下载订单信息",
					paramMap.get("startTime") + ":" + paramMap.get("endTime"), e.getMessage()));
		} catch (SQLException e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(shopVO.getShopAccount(), "通过店铺下载订单信息",
					paramMap.get("startTime") + ":" + paramMap.get("endTime"), e.getMessage()));
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			logUtil.error(new DBLog(shopVO.getShopAccount(), "通过店铺下载订单信息",
					paramMap.get("startTime") + ":" + paramMap.get("endTime"), e.getMessage()));
		} finally {
			try {
				if (conn != null && !conn.isClosed()) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
				logger.error(e.getMessage(), e);
			}
		}
		return map;
	}

	/**
	 * 利用jdbc直接访问聚石塔的表取得返回的结果集
	 *
	 * @param paramMap
	 * @return 里面分别保存trade和order的数据
	 */
	private List<TaoBaoOrder> getTradeFromTaoBaoList(Map<String, Object> paramMap, int startRow, int endRow) {
		StringBuilder sql = new StringBuilder(); // sql语句
		List<TaoBaoOrder> list = new ArrayList<TaoBaoOrder>(); // 解析检索得到的json
		// 如果店铺名称没有，就取消操作
		ShopVO shopVO = (ShopVO) paramMap.get("shop");
		if (shopVO == null) {
			return null;
		}
		try {
			// 生成SQL语句
			sql.append(" select tid,jdp_response");
			sql.append(" from " + TABLENAME);
			sql.append(" where seller_nick = '" + shopVO.getShopAccount() + "'");
			if (paramMap.containsKey("startTime") && paramMap.containsKey("endTime")
					&& paramMap.get("startTime") != null && paramMap.get("endTime") != null) {
				sql.append(" and modified >= '" + paramMap.get("startTime") + "'");
				sql.append(" and modified <= '" + paramMap.get("endTime") + "'");
			}
			// 手动下载用
			if (StringUtils.isNotBlank((String) paramMap.get("tid"))) {
				sql.append(" and tid = '" + paramMap.get("tid") + "'");
			}
			// 手动下载用
			if (StringUtils.isNotBlank((String) paramMap.get("buyerNick"))) {
				sql.append(" and buyer_nick = '" + paramMap.get("buyerNick") + "'");
			}

            sql.append(" order by modified");
			sql.append(" LIMIT " + startRow + ", " + endRow);

            logger.info(shopVO.getShopAccount()+"-RDS查询语句为："+sql.toString());

			QueryRunner qr = getQueryRunner(shopVO.getShopId(), shopVO.getDbUrl(), shopVO.getDbUsername(),
					shopVO.getDbPassword());
			List<Map<String, Object>> mapLs = qr.query(sql.toString(), new MapListHandler());
			for (Map<String, Object> resultmap : mapLs) {
				TaoBaoOrder taoBaoOrder = new TaoBaoOrder();
				taoBaoOrder.setTid(resultmap.get("tid").toString());
				taoBaoOrder.setTaoBaoResponse(
						getObjectFromJson(resultmap.get("jdp_response").toString(), "trade_fullinfo_get_response"));
				list.add(taoBaoOrder);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(shopVO.getShopAccount() +"-RDS执行语句异常"+ e.getMessage(), e);

			logUtil.error(new DBLog(shopVO.getShopAccount(), "通过店铺下载订单信息",
					paramMap.get("startTime") + ":" + paramMap.get("endTime"), e.getMessage()));
		}
		return list;
	}

	/**
	 * json解析成为对象，由于json中含有数组，所以要特殊处理
	 *
	 * @param json
	 * @return
	 */
	private TaoBaoResponse getObjectFromJson(String json, String title) {
		JSONObject object = JSON.parseObject(json).getJSONObject(title).getJSONObject("trade");
		// 解析orders数组
		JSONArray orderArray = object.getJSONObject("orders").getJSONArray("order");
		List<cn.rkylin.oms.order.vo.Order> orderList = new ArrayList<cn.rkylin.oms.order.vo.Order>();
		if (null != orderArray) {
			orderList = JSON.parseArray(orderArray.toJSONString(), cn.rkylin.oms.order.vo.Order.class);
		}
		object.remove("orders");

		// 解析promotion_details数组
		JSONArray promotionArray = object.getJSONObject("promotion_details") == null ? null
				: object.getJSONObject("promotion_details").getJSONArray("promotion_detail");
		List<Promotion_detail> promotionList = new ArrayList<Promotion_detail>();
		if (null != promotionArray) {
			promotionList = JSON.parseArray(promotionArray.toJSONString(), Promotion_detail.class);
		}
		object.remove("promotion_details");

		// 解析service_tags数组(数组里面套数组的情况)
		JSONArray serviceArray = object.getJSONObject("service_tags") == null ? null
				: object.getJSONObject("service_tags").getJSONArray("logistics_tag");
		List<Logistics_tag> serviceList = new ArrayList<Logistics_tag>();// logistic_service_tag_list
		if (serviceArray != null) {
			for (int i = 0; i < serviceArray.size(); i++) {
				JSONObject entityObj = serviceArray.getJSONObject(i);
				JSONArray logisticServiceArray = entityObj.getJSONObject("logistic_service_tag_list")
						.getJSONArray("logistic_service_tag");
				List<Logistic_service_tag> logisticServiceList = new ArrayList<Logistic_service_tag>();
				if (null != logisticServiceArray) {
					logisticServiceList = JSON.parseArray(logisticServiceArray.toJSONString(),
							Logistic_service_tag.class);
				}
				entityObj.remove("logistic_service_tag_list");
				Logistics_tag logistics_tag = JSON.parseObject(entityObj.toJSONString(), Logistics_tag.class);
				serviceList.add(logistics_tag);
			}
		}
		object.remove("service_tags");

		// 将数组的json对应的对象加入
		Trade trade = JSON.parseObject(object.toJSONString(), Trade.class);
		if (orderList != null && orderList.size() > 0) {
			trade.setOrders(orderList);
		}
		if (promotionList != null && promotionList.size() > 0) {
			trade.setPromotion_details(promotionList);
		}
		if (serviceList != null && serviceList.size() > 0) {
			trade.setService_tags(serviceList);
		}
		TaoBaoResponse taoBaoResponse = new TaoBaoResponse();
		TradeFullInfo tradeFullInfo = new TradeFullInfo();
		tradeFullInfo.setTrade(trade);
		taoBaoResponse.setTrade_fullinfo_get_response(tradeFullInfo);

		return taoBaoResponse;
	}

	/**
	 * 获取指定时间范围内的订单列表
	 *
	 * @param startTime
	 * @param endTime
	 * @param paramMap
	 */
	public int getOrderList(Date startTime, Date endTime, Map<String, String> paramMap) {

		return 0;
	}

	/**
	 *
	 *
	 * @param orderNumber
	 * @param paramMap
	 */
	public Order getOrder(String orderNumber, Map<String, String> paramMap) {
		Order returnOrder = new Order();
		return returnOrder;
	}

	/**
	 * 保存平台订单
	 */
	protected void saveOrder() {

	}

	/**
	 * 获取指定时间范围内的订单列表
	 *
	 * @param paramMap
	 */
	public List<Order> getOrderList(Map<String, String> paramMap) {
		return null;
	}

    /**
     * 获取trade,order 列表，双11，1分钟内可能几十万单，以30条为单位，获取淘宝订单
     *
     * @param paramMap
     */
    public void getOrderObjectList(Map<String, Object> paramMap, Integer startRow,Integer endRow, List<TaoBaoOrder> loopList) {
		List<TaoBaoOrder> taoBaoList = getTradeFromTaoBaoList(paramMap, startRow, endRow);
		for (TaoBaoOrder tb:taoBaoList ) {
			loopList.add(tb);
		}
	}

	/**
	 * 获取trade,order 列表
	 *
	 * @param paramMap
	 */
	public Map<String, Object> getOrderObject(Map<String, Object> paramMap) {
		return getTradeFromTaoBao(paramMap);
	}

	/**
	 * 平台发货
	 *
	 * @param paramMap
	 *            return 结果Map
	 * @throws Exception
	 *             异常
	 */
	public Map<String, Object> consign(Map<String, Object> paramMap) throws Exception {
		Map<String, Object> returnMap = new HashMap<String, Object>();

		ShopVO shopVO = (ShopVO) paramMap.get("shop");
		// 查询需要平台发货的信息
		List<ShiporderVO> shipOrderList = shiporderServiceImpl.selectByShopVoShipOrderConsign(shopVO);
		// 轮询发货
		for (int i = 0; i < shipOrderList.size(); i++) {
			ShiporderVO shiporderVO = shipOrderList.get(i);
			// 如果是合并的订单
			if (shiporderVO.getTradeCode().indexOf(",") != -1) {
				String[] tradeCodeSplit = shiporderVO.getTradeCode().split(",");
				for (String temp : tradeCodeSplit) {

					// 平台发货
					consignApi(temp, shopVO, shiporderVO);
				}
				continue;
			}

			// 非合并订单
			// 平台发货
			consignApi(shiporderVO.getTradeCode(), shopVO, shiporderVO);
		}
		returnMap.put("success", "true");
		returnMap.put("msg", "");
		return returnMap;
	}

	/**
	 * 平台发货 - 调用TOPAPI
	 *
	 * @param shopId
	 *            网店id
	 * @param tradeCode
	 *            平台交易号
	 * @param lgstCode
	 *            物流公司编码
	 * @param lgstName
	 *            物流公司名称
	 * @param lgstNo
	 *            运单号
	 * @throws Exception
	 */
	private void consignApi(String tradeCode, ShopVO shopVO, ShiporderVO shiporderVO) throws Exception {

		// 拆包发货相关业务 start
		// 获取平台订单信息
		Map<String, Object> reqMap = new HashMap<String, Object>();
		reqMap.put("ecTradeCode", tradeCode);
		reqMap.put("shopId", shopVO.getShopId());
		cn.rkylin.oms.order.domain.EcTrade ecTrade = orderServiceImpl.selectByEcTradeCodeAndShopIdEcTrade(reqMap);
		if (ecTrade == null) {
			return;
		}
		// 判断平台订单状态
		// EB_WAIT_BUYER_PAY(等待买家付款)
		// EB_WAIT_SELLER_SEND(等待卖家发货,即:买家已付款) EB_TRADE_PARTIALLY_SEND(交易部分发货)
		// EB_TRADE_ALL_SEND(交易全部发货) EB_TRADE_FINISHED(交易成功)
		// EB_TRADE_CANCELED(交易取消)
		if ("EC_TRADE_FINISHED".equals(ecTrade.getEcTradeStatus())
				|| "EC_TRADE_CANCELED".equals(ecTrade.getEcTradeStatus())) {
			// 保存数据
			consignSaveData(shopVO, shiporderVO, false);
			return;
		}
		// 拆包发货相关业务 end

		// 调用平台发货接口
		cn.rkylin.oms.warehouse.shiporder.request.RequestTradeOfflineSend requestTradeOfflineSend = null;
		requestTradeOfflineSend = new RequestTradeOfflineSend();
		requestTradeOfflineSend.setEcTradeCode(tradeCode);
		requestTradeOfflineSend.setLgstCode(shiporderVO.getLgstCode());
		requestTradeOfflineSend.setLgstName(shiporderVO.getLgstName());
		requestTradeOfflineSend.setLgstNo(shiporderVO.getLgstNo());
		Map<String, String> execMap = shiporderServiceImpl.pushOfflineSend(shopVO.getShopId(), requestTradeOfflineSend);
		if (execMap.containsKey("success")) {
			// 成功
			if ("y".equals(execMap.get("success"))) {
				// 保存数据
				consignSaveData(shopVO, shiporderVO, true);
			}
			// 失败
			if ("n".equals(execMap.get("success"))) {
				String errMsg = execMap.get("msg");
				// 记录日志发货单
				logUtil.info(new DBLog(shiporderVO.getShiporderCode(), "", "consign",
						DateUtil.getCurrentDateStr() + "  发货单: 系统自动平台发货任务, 发货失败: " + errMsg));
			}
		} else {
			// 记录日志发货单
			logUtil.info(new DBLog(shiporderVO.getShiporderCode(), "", "consign",
					DateUtil.getCurrentDateStr() + "  发货单: 系统自动平台发货任务, 发货失败: " + "远程连接错误或请求不正确"));
		}
	}

	/**
	 * 平台发货 - 数据保存
	 *
	 * @author jipengcheng
	 * @param shiporderVO
	 * @throws Exception
	 */
	private void consignSaveData(ShopVO shopVO, ShiporderVO shiporderVO, Boolean isUpdateSysOrder) throws Exception {

		if (isUpdateSysOrder) {
			// 更新订单
			cn.rkylin.oms.sysOrder.vo.SysOrderVO sysOrderVOUpdate = new SysOrderVO();
			sysOrderVOUpdate.setTradeCode(shiporderVO.getTradeCode());
			sysOrderVOUpdate.setShopId(shopVO.getShopId());
			sysOrderVOUpdate.setConsignTime(new Date());
			sysOrderServiceImpl.updateByPrimaryKeySelectiveSysOrder(sysOrderVOUpdate);
		}

		// 更新发货单
		cn.rkylin.oms.warehouse.shiporder.vo.ShiporderVO shiporderVOUpdate = new ShiporderVO();
		shiporderVOUpdate.setShiporderCode(shiporderVO.getShiporderCode());
		shiporderVOUpdate.setConsignStatus("y");
		shiporderVOUpdate.setConsignTime(cn.rkylin.oms.common.utils.DateUtil.formatDate(new Date()));
		shiporderServiceImpl.updateByPrimaryKeySelectiveShipOrder(shiporderVOUpdate);

		// 记录日志发货单
		logUtil.info(new DBLog(shiporderVO.getShiporderCode(), "", "consign",
				DateUtil.getCurrentDateStr() + "  发货单: 系统自动平台发货任务, 发货成功!"));
	}

	/**
	 * 临时先放这里，只有这里用，apache DBUtils + apache dbcp
	 *
	 * @author wangxiaoyi
	 * @param url
	 * @param userName
	 * @param password
	 * @return
	 */
	private synchronized QueryRunner getQueryRunner(String shopId, String url, String userName, String password)
			throws Exception {
		QueryRunner returnRunner = null;
		BasicDataSource shopDataSource = dataSourceMap.get(shopId);
		if (shopDataSource == null) {
			// 使用dbcp实现数据源连接池
			shopDataSource = new BasicDataSource();
			shopDataSource.setDriverClassName("com.mysql.jdbc.Driver");
			shopDataSource.setUrl(url);
			shopDataSource.setUsername(userName);
			shopDataSource.setPassword(password);
			// TODO
			// 下面这些参数，应该随着店铺数的增多而调整，应该配置到pom.xml里，根据测试环境和生产环境来调整（2017年12月14日）
			shopDataSource.setInitialSize(5);// 初始化的连接数
			shopDataSource.setMaxActive(4);// 最大的连接数
			shopDataSource.setMaxIdle(4);// 最大空闲数
			shopDataSource.setMinIdle(2);// 最小空闲数
			shopDataSource.setDefaultReadOnly(true);
			dataSourceMap.put(shopId, shopDataSource);
		}
		returnRunner = new QueryRunner(shopDataSource);
		return returnRunner;
	}
}